<?php

Yii::import("application.commands.ClusterCommand");
class ClusterSyncCommand extends ClusterCommand {
    private static $instance;
    private $problems = array();
    private $initialProblems = array();
    private $downloadedProblems = array();
    private $localProblems = array();
    private $downloadedFiles = array();
    private $lastSync;

    public static function instance() {
        return self::$instance;
    }

    private function getProblems() {
        echo "\tGetting problem list....\n";
        curl_setopt ($this->curlChannel, CURLOPT_URL, $this->createUrl('supervisor/cluster/getproblems?key=itbitbitb'));
        $content = curl_exec($this->curlChannel);
        $fields = json_decode($content , true);
        $this->problems = $fields['problems'];
        $this->lastSync = $fields['update_time'];
    }
    
    private function getInitialProblems() {
        echo "\tGetting initial problem list....\n";
        curl_setopt ($this->curlChannel, CURLOPT_URL, $this->createUrl('supervisor/cluster/getinitialproblems?key=itbitbitb'));
        $content = curl_exec($this->curlChannel);
        $fields = json_decode($content , true);
        $this->initialProblems = $fields['problems'];
        $this->lastSync = $fields['update_time'];
    }
    
    private function getProblemMeta($id) {
        curl_setopt ($this->curlChannel, CURLOPT_URL, $this->createUrl('supervisor/cluster/getproblem/id/'.$id.'?key=itbitbitb'));
        $content = curl_exec($this->curlChannel);
        return json_decode($content , true);
    }
    
    private function downloadInitialProblems() {
        echo "\tDownloading initial problems...";
        foreach ($this->initialProblems as $id => $obj) {
            if (Problem::model()->findByPK($id) === NULL) {
                echo "\t\tCreating meta for problem #" . $id . "\n";          
                $p = new Problem("Create");
    			$p->id = $id;
    			$p->title = "a";
    			$p->problem_type_id = 0;
    			$p->visibility = 0;
    			$p->description = "a";
    			$p->token = $obj['token'];   
    			$p->save(false);                
            
                echo "\t\tDownloading problem #" . $id . "\n";
                $meta = $this->getProblemMeta($id);
                $downloadedFiles = array();
                $downloadedFiles[$id] = array();
                foreach ($meta['checksum'] as $file => $checksum) {
                    if ($checksum !== '.') {                        
                        $downloadedFiles[$id][] = $file;
                    }
                    else {
                        mkdir($p->getDirectoryPath() . $file , 0777 , true);
                    }
                }
                
                foreach ($downloadedFiles as $pid => $files) {
                    foreach ($files as $file)
                        $this->downloadFile($pid , $file);
                }
                $p->modified_date = $meta['modified_date'];
                $p->save(false);
            }
        } 
    }

    private function synchronizeProblems() {
        $localProblems = Problem::model()->findAll();

        $localTokens = array();
        foreach ($localProblems as $problem) {
            $localTokens[$problem->id] = $problem;
        }

        foreach ($this->problems as $id => $problem) {
            if (!isset($localTokens[$id])) {
                echo "CREATING NEW PROBLEM RECORD\n";
                $p = new Problem("Create");
    			$p->id = $id;
    			$p->title = "a";
    			$p->problem_type_id = 0;
    			$p->visibility = 0;
    			$p->description = "a";
    			$p->token = $problem['token'];   
    			$p->modified_date = $problem['modified_date'];
    			$p->save(false);         
            
                foreach ($problem['checksum'] as $file => $checksum) {
                    if ($checksum !== '.') {                        
                        $this->downloadedFiles[$id][] = $file;
                    }
                    else {
                        mkdir($p->getDirectoryPath() . $file , 0777 , true);
                    }
                }
            }
            else {
                $eProblem = Problem::model()->findByPK($id);
                $localChecksum = $eProblem->generateChecksum();
                
                //print_r($localChecksum);
                //print_r($problem['checksum']);                
                foreach ($problem['checksum'] as $file => $checksum) {
                    if (!isset($localChecksum[$file]) || $localChecksum[$file] !== $checksum) {
                        if ($checksum !== '.') {                        
                            $this->downloadedFiles[$id][] = $file;
                        }
                        else {
                            mkdir($eProblem->getDirectoryPath() . $file , 0777 , true);
                        }
                    }
                }
                
                $eProblem->modified_date = $problem['modified_date'];
                $eProblem->save(false);
            }
        }

        /*if (count($this->downloadedProblems) !== 0) {
            echo "\n" . "DOWNLOADS" . "\n";
            print_r($this->downloadedProblems);
        }*/
    }

    /*private function downloadProblems() {
        foreach ($this->downloadedProblems as $id => $problem) {
            $this->downloadProblem($id , Yii::app()->params->config['evaluator']['problem']['problem_repository_path'] . '/' . $problem . ".zip");
        
            $p = Problem::model()->findByPK($id);
            if ($p === null) {
			    $p = new Problem("Create");
    			$p->id = $id;
    			$p->title = "a";
    			$p->problem_type_id = 0;
    			$p->visibility = 0;
    			$p->description = "a";
    			$p->token = $problem;
    			echo $p->save(false) == 0;
			}   
			else {
                $p->modified_date = new CDbExpression("NOW()");
                $p->save();			
			}
        }

        if (count($this->downloadedProblems) != 0)
            $this->localProblems = $this->downloadedProblems;
    }*/
    
    private function downloadFiles() {
        foreach ($this->downloadedFiles as $id => $files) {
            foreach ($files as $file) {
                $this->downloadFile($id , $file);
            }
        }
    }
    
    private function downloadFile($id , $path) {
        echo "Downloading file " . $path . " for problem #" . $id . "\n";
        curl_setopt ($this->curlChannel, CURLOPT_URL, $this->createUrl("supervisor/cluster/getfile/id/$id?key=itbitbitb&path=" . $path));
        $content = curl_exec($this->curlChannel);
        //echo $content;
        
        $problem = Problem::model()->findByPK($id);
        file_put_contents($problem->getDirectoryPath() . "/" . $path , $content);
    }

    public function run($args) {
        self::$instance = $this;
        $this->baseUrl = $args[0];
        $this->username = $args[1];
        $this->password = $args[2];

        echo "Attempting to log on to ".$this->baseUrl."..... \n";
        if($this->login($this->username , $this->password)) {
                echo "\tLogin success\n\n";
                
            $this->getInitialProblems();
            $this->downloadInitialProblems();

            echo sprintf("Synchronizing\n");
            for(;;) {
                $this->problems = array();
                $this->downloadedProblems = array();
                $this->downloadedFiles = array();

                $this->getProblems();
                $this->synchronizeProblems();
                $this->downloadFiles();

                //$this->downloadProblem();
                echo "\t\tNO SYNC\n";
                sleep(2);
            }
        }
        else
        	echo "Login failed\n";
    }
}

?>